#include <ltCmdList.h>
#include <crcCalc.h>
#include <hexstr.h>
const char *LT_PTC_SUB_VERSION = "LTPT-STD-V1.1.2407131959";

// =============command rwSn(write or read serial number) begin=====================
void ltCmdFunOvtiDef(rwSn)(struct ltCmdStciDef(rwSn) * idt)
{
    idt = NULL;
}
void ltCmdFunOvtoDef(rwSn)(struct ltCmdStcoDef(rwSn) * odt)
{
    odt = NULL;
}
#if LT_PTC_CMD_SUB_ENABLE
void ltCmdFunSubDoDef(rwSn)(union ltCmdUnionDef(rwSn) * iodt, struct ltPtcPsStc *ptcptr)
{
    if (memcmp(parmNormIstc.sn, LT_CMD_DEFAULT_SN, LT_CMD_SN_MAX_SIZE) == 0)
    {
        logdebug("sub cfg sn ok, my sn:%s, cfg sn:%s", getHexBufStr(parmNormIstc.sn).str, getHexBufStr(iodt->idt.wSn).str);
        memcpy(parmNormIstc.sn, iodt->idt.wSn, LT_CMD_SN_MAX_SIZE);
        // save param
        parmNormSave();
    }
    else
    {
        logdebug("sub cfg sn fail, my sn:%s, cfg sn:%s", getHexBufStr(parmNormIstc.sn).str, getHexBufStr(iodt->idt.wSn).str);
    }
    memcpy(iodt->odt.rSn, parmNormIstc.sn, LT_CMD_SN_MAX_SIZE);
    ptcptr->subRespSizeHostCmdId = sizeof(iodt->odt);
}
#endif
#if LT_PTC_CMD_HOST_ENABLE
int ltCmdFunHostPackDef(rwSn)(struct ltPtcPsStc *ptcptr, const char *inwSn)
{
    struct ltCmdStciDef(rwSn) *tmpdata = (struct ltCmdStciDef(rwSn) *)ltPtcGetDataPtrV1(ptcptr);
    memcpy(tmpdata->wSn, inwSn, sizeof(tmpdata->wSn));
    memcpy(ptcptr->hostSndInf, inwSn, sizeof(tmpdata->wSn));
    return ltPtcHostPackCommV1(ptcptr, 0xff, ltPtcCrypte_None, ltCmdEnumDef(rwSn), sizeof(struct ltCmdStciDef(rwSn)));
}
int ltCmdFunHostDealDef(rwSn)(struct ltCmdStcoDef(rwSn) * odt, struct ltPtcPsStc *ptcptr)
{
    // logDebugHexBuf(odt->rSn, sizeof(odt->rSn));
    if (memcmp(ptcptr->hostSndInf, odt->rSn, sizeof(odt->rSn)) != 0)
    {
        logwarn("host cfg sn fail:%s!=%s", getHexBufStr(ptcptr->hostSndInf).str, getHexBufStr(odt->rSn).str);
    }
    else
    {
        logwarn("host cfg sn ok:%s=%s", getHexBufStr(ptcptr->hostSndInf).str, getHexBufStr(odt->rSn).str);
    }
    return 1;
}
#endif
// =============command rwSn(write or read serial number) begin=====================

// =============command rwAddr(write or read address) begin=====================
void ltCmdFunOvtiDef(rwAddr)(struct ltCmdStciDef(rwAddr) * idt)
{
    idt = NULL;
}
void ltCmdFunOvtoDef(rwAddr)(struct ltCmdStcoDef(rwAddr) * odt)
{
    odt = NULL;
}
#if LT_PTC_CMD_SUB_ENABLE
void ltCmdFunSubDoDef(rwAddr)(union ltCmdUnionDef(rwAddr) * iodt, struct ltPtcPsStc *ptcptr)
{
    if (memcmp(parmNormIstc.sn, iodt->idt.cfgSn, LT_CMD_SN_MAX_SIZE))
    {
        ptcptr->subRespStatFlag = ltPtcCmdResp_NotSndBack;
        return;
    }
    logdebug("sub cfg add:my=%d,set=%d", parmNormIstc.addr485, iodt->idt.wAddr);
    if (iodt->idt.rwflag)
    {
        parmNormIstc.addr485 = iodt->idt.wAddr;
        // save param
        parmNormSave();
    }
    iodt->odt.rAddr = parmNormIstc.addr485;
    // ltPtcSetAddrV1(ptcptr, parmNormIstc.addr485);
    ptcptr->subRespSizeHostCmdId = sizeof(iodt->odt);
}
#endif
#if LT_PTC_CMD_HOST_ENABLE
int ltCmdFunHostPackDef(rwAddr)(struct ltPtcPsStc *ptcptr, const char *inSn, const char inaddr, const char inflag)
{
    struct ltCmdStciDef(rwAddr) *tmpdata = (struct ltCmdStciDef(rwAddr) *)ltPtcGetDataPtrV1(ptcptr);
    memcpy(tmpdata->cfgSn, inSn, sizeof(tmpdata->cfgSn));
    tmpdata->rwflag = inflag;
    tmpdata->wAddr = inaddr;
    ptcptr->hostSndInf[0] = inaddr;
    return ltPtcHostPackCommV1(ptcptr, 0xff, ltPtcCrypte_None, ltCmdEnumDef(rwAddr), sizeof(struct ltCmdStciDef(rwAddr)));
}
int ltCmdFunHostDealDef(rwAddr)(struct ltCmdStcoDef(rwAddr) * odt, struct ltPtcPsStc *ptcptr)
{
    if (ptcptr->hostSndInf[0] != odt->rAddr)
    {
        logerror("host set addr error:%d!=%d", ptcptr->hostSndInf[0], odt->rAddr);
        return -1;
    }
    else
    {
        logdebug("host set addr ok:%d=%d", ptcptr->hostSndInf[0], odt->rAddr);
    }
    return 1;
}
#endif
// =============command rwAddr(write or read address) end======================

// =============command getInf begin=====================
void ltCmdFunOvtiDef(getInf)(struct ltCmdStciDef(getInf) * idt)
{
    idt = NULL;
}
void ltCmdFunOvtoDef(getInf)(struct ltCmdStcoDef(getInf) * odt)
{
    odt->dlgcrc = ovtBigSys16(odt->dlgcrc);
}
#if LT_PTC_CMD_SUB_ENABLE
void ltCmdFunSubDoDef(getInf)(union ltCmdUnionDef(getInf) * iodt, struct ltPtcPsStc *ptcptr)
{
#if LT_PTC_CMD_USE_CRYPTE
    // in, get inform command will set dialog key, so need crypte.
    if (ltPtcGetCrypteV1(ptcptr) != ltPtcCrypte_Sm4Pre)
    {
        logerror("");
        ptcptr->subRespStatFlag = ltPtcCmdResp_NdCrypt;
        return;
    }
    memcpy(ptcptr->ltPtcKeyDlg, iodt->idt.dlgKey, sizeof(iodt->idt.dlgKey));
    // out
    iodt->odt.dlgcrc = calcSumCrc16((const uint8_t *)ptcptr->ltPtcKeyDlg, sizeof(ptcptr->ltPtcKeyDlg));
#endif
    memset(iodt->odt.rvers, 0, sizeof(iodt->odt.rvers));
    memcpypro(iodt->odt.rvers, sizeof(iodt->odt.rvers), LT_PTC_SUB_VERSION, strlen(LT_PTC_SUB_VERSION));
    memcpy(iodt->odt.rsn, parmNormIstc.sn, LT_CMD_SN_MAX_SIZE);
    // response no need encrypte, there just for check.
#if LT_PTC_CMD_USE_CRYPTE
    ptcptr->subRespCrypteHostAddr = ltPtcCrypte_Sm4Pre;
#endif
    ptcptr->subRespSizeHostCmdId = sizeof(iodt->odt);
}
#endif
#if LT_PTC_CMD_HOST_ENABLE
int ltCmdFunHostPackDef(getInf)(struct ltPtcPsStc *ptcptr, uint8_t inaddr, const char *inkey)
{
#if LT_PTC_CMD_USE_CRYPTE
    struct ltCmdStciDef(getInf) *tmpdata = (struct ltCmdStciDef(getInf) *)ltPtcGetDataPtrV1(ptcptr);
    memcpy(tmpdata->dlgKey, inkey, sizeof(tmpdata->dlgKey));
    memcpy(ptcptr->ltPtcKeyDlg, inkey, sizeof(ptcptr->ltPtcKeyDlg));
    *((uint16_t *)(ptcptr->hostSndInf)) = calcSumCrc16((const uint8_t *)tmpdata->dlgKey, sizeof(tmpdata->dlgKey));
    return ltPtcHostPackCommV1(ptcptr, inaddr, ltPtcCrypte_Sm4Pre, ltCmdEnumDef(getInf), sizeof(struct ltCmdStciDef(getInf)));
#else
    return ltPtcHostPackCommV1(ptcptr, inaddr, ltPtcCrypte_None, ltCmdEnumDef(getInf), sizeof(struct ltCmdStciDef(getInf)));
#endif
}
int ltCmdFunHostDealDef(getInf)(struct ltCmdStcoDef(getInf) * odt, struct ltPtcPsStc *ptcptr)
{
#if LT_PTC_CMD_USE_CRYPTE
    if (ltPtcGetCrypteV1(ptcptr) != ltPtcCrypte_Sm4Pre)
    {
        logerror("%d", ltPtcGetCrypteV1(ptcptr));
        return -1;
    }
    logdebug("%d", odt->dlgcrc);
    if (*((uint16_t *)(ptcptr->hostSndInf)) != odt->dlgcrc)
    {
        logerror("%d!=%d", *((uint16_t *)(ptcptr->hostSndInf)), odt->dlgcrc);
        return -1;
    }
#endif
    logdebug("host rcv sub vers: %s", odt->rvers);
    return 1;
}
#endif
// =============command getInf end======================

// =============command heartBeat begin=====================
void ltCmdFunOvtiDef(heartBeat)(struct ltCmdStciDef(heartBeat) * idt)
{
    idt = NULL;
}
void ltCmdFunOvtoDef(heartBeat)(struct ltCmdStcoDef(heartBeat) * odt)
{
    odt = NULL;
}
#if LT_PTC_CMD_SUB_ENABLE
void ltCmdFunSubDoDef(heartBeat)(union ltCmdUnionDef(heartBeat) * iodt, struct ltPtcPsStc *ptcptr)
{
    // in
    logdebug("sub rcv heartbeat:%s", iodt->idt.resvSnd);
    // out
    strcpy(iodt->odt.resvResp, "heartsub");
    // lcoPtr->subRespStatFlag = ltPtcCmdResp_OK;
    ptcptr->subRespCrypteHostAddr = ltPtcCrypte_Sm4Dlg;
    ptcptr->subRespSizeHostCmdId = sizeof(iodt->odt);
    return;
}
#endif
#if LT_PTC_CMD_HOST_ENABLE
int ltCmdFunHostPackDef(heartBeat)(struct ltPtcPsStc *ptcptr, uint8_t inaddr, const char *inres)
{
    struct ltCmdStciDef(heartBeat) *tmpdata = (struct ltCmdStciDef(heartBeat) *)ltPtcGetDataPtrV1(ptcptr);
    strncpy(tmpdata->resvSnd, inres, sizeof(tmpdata->resvSnd));
    return ltPtcHostPackCommV1(ptcptr, inaddr, ltPtcCrypte_Sm4Dlg, ltCmdEnumDef(heartBeat), sizeof(struct ltCmdStciDef(heartBeat)));
}
int ltCmdFunHostDealDef(heartBeat)(struct ltCmdStcoDef(heartBeat) * odt, struct ltPtcPsStc *ptcptr)
{
    logdebug("host rcv heart: %s", odt->resvResp);
    return 1;
}
#endif
// =============command heartBeat end======================

#if LT_PTC_CMD_SUB_ENABLE
#define SWITH_SUB_CMD_ID_FUNC(cmdname)                                                                \
    case ltCmdEnumDef(cmdname):                                                                       \
    {                                                                                                 \
        ltCmdFunOvtiDef(cmdname)((struct ltCmdStciDef(cmdname) *)ltPtcGetDataPtrV1(ptcptr));          \
        ltCmdFunSubDoDef(cmdname)((union ltCmdUnionDef(cmdname) *)ltPtcGetDataPtrV1(ptcptr), ptcptr); \
        ltCmdFunOvtoDef(cmdname)((struct ltCmdStcoDef(cmdname) *)ltPtcGetDataPtrV1(ptcptr));          \
        break;                                                                                        \
    }
void ltCmdSubDealByID(struct ltPtcPsStc *ptcptr)
{
    switch (ltPtcGetCmdIdV1(ptcptr))
    {
        SWITH_SUB_CMD_ID_FUNC(rwSn);
        SWITH_SUB_CMD_ID_FUNC(rwAddr);
        SWITH_SUB_CMD_ID_FUNC(getInf);
        SWITH_SUB_CMD_ID_FUNC(heartBeat);
    default:
    {
        logerror("%d", ltPtcGetCmdIdV1(ptcptr));
        break;
    }
    }
}
#endif

#if LT_PTC_CMD_HOST_ENABLE
#define SWITH_HOST_CMD_ID_FUNC(cmdname)                                                                         \
    case ltCmdEnumDef(cmdname):                                                                                 \
    {                                                                                                           \
        ltCmdFunOvtoDef(cmdname)((struct ltCmdStcoDef(cmdname) *)ltPtcGetDataPtrV1(ptcptr));                    \
        return ltCmdFunHostDealDef(cmdname)((struct ltCmdStcoDef(cmdname) *)ltPtcGetDataPtrV1(ptcptr), ptcptr); \
    }
int ltCmdHostDealByID(struct ltPtcPsStc *ptcptr)
{
    switch (ltPtcGetCmdIdV1(ptcptr))
    {
        SWITH_HOST_CMD_ID_FUNC(rwSn);
        SWITH_HOST_CMD_ID_FUNC(rwAddr);
        SWITH_HOST_CMD_ID_FUNC(getInf);
        SWITH_HOST_CMD_ID_FUNC(heartBeat);
    default:
    {
        logerror("%d", ltPtcGetCmdIdV1(ptcptr));
        break;
    }
    }
    return 0;
}
#endif
